package com.zxl.chatroomserver;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * server of chat room
 */
public class ChatRoomServer implements Runnable {

    private Selector selector;
    private volatile boolean stop;


    public ChatRoomServer(int port) throws IOException {
        System.out.println(" server starting~~~~~~ ");
        selector = Selector.open();
        ServerSocketChannel serverSocketChannel = null;
        // 创建channel
        serverSocketChannel = ServerSocketChannel.open();
        //设置非阻塞
        serverSocketChannel.configureBlocking(false);
        //bind端口
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", port));
        //将事件和channel注册到selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);


        System.out.println(" server start finished");
    }

    public void start()  {
        while (!stop){
            try {
                selector.select(1000);
                Set selectionKeys = selector.selectedKeys();
                Iterator it = selectionKeys.iterator();
                SelectionKey key=null;
                while (it.hasNext()) {
                    key= (SelectionKey) it.next();
                    it.remove();
                    try {
                        handleInput(key);
                    }catch (Exception e){
                        if(key!=null){
                            key.cancel();
                            if(key.channel()!=null){
                                key.channel().close();
                            }
                        }
                    }
                }
            }catch (Throwable t){
                t.printStackTrace();
            }
        }


        if(selector!=null){
            try {
                selector.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }

    }


    private void handleInput(SelectionKey key) throws IOException {
        //接收一个新的connect
        if (key.isAcceptable()) {
            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
            SocketChannel sc = ssc.accept();
            sc.configureBlocking(false);
            sc.register(selector, SelectionKey.OP_READ);
        }

        if (key.isReadable()) {
            SocketChannel sc = (SocketChannel) key.channel();
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int readSize = sc.read(readBuffer);
            if (readSize > 0) {
                readBuffer.flip();
                byte[] bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                String body = new String(bytes, "UTF-8");
                System.out.println("服务端接收到消息：" + body);
                sendMsg(sc);
            } else if (readSize < 0) {
                //关闭链路
                key.cancel();
                sc.close();
            } else {
            }

        }
    }


    private void sendMsg(SocketChannel sc) throws IOException {
        byte[] req = "hi, i am server !".getBytes();
        ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
        writeBuffer.put(req);
        writeBuffer.flip();
        sc.write(writeBuffer);
        //判断缓冲区是否写入完成
        if (!writeBuffer.hasRemaining()) {
            System.out.println("服务端消息发送完成 ！！！");
        }

    }


    @Override
    public void run() {
            start();
    }
}
